package com.njcb.ams.service;

import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

import com.njcb.ams.util.AmsParamUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.stereotype.Service;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.njcb.ams.factory.domain.AppContext;
import com.njcb.ams.portal.SysBaseDefine;
import com.njcb.ams.support.exception.ExceptionUtil;
import com.njcb.ams.util.AmsBeanUtils;

/**
 * 将datagrid表格数据导出为excel
 *
 * @author liuyanlong
 */
@Service
public class ExportService {

    public static ExportService getInstance() {
        return AppContext.getBean(ExportService.class);
    }

    /**
     * @param titleNameArray  excel标题
     * @param titleValueArray excel数据
     * @return
     * @throws IOException
     */
    public String exportData(List<String> titleNameArray, List<String> titleValueArray, List<Object> dataListArray, Map<String, Map<String, String>> dataDicList, OutputStream outputStream) {
        try {
            exportExcel(titleNameArray, titleValueArray, dataListArray, dataDicList, outputStream);
            outputStream.flush();
            if (outputStream != null) {
                outputStream.close();
            }
        } catch (Exception e) {
            ExceptionUtil.printStackTrace(e);
            ExceptionUtil.throwAppException("生成EXCEL不正确:" + e.getMessage());
        }
        return "";
    }

    /**
     * 写入流
     *
     * @param os
     * @throws IOException
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    public void exportExcel(List<String> fieldNameArray, List<String> fieldValueArray,
                            List<Object> fieldDataList, Map<String, Map<String, String>> dataDicList, OutputStream os)
            throws IOException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        SXSSFWorkbook workBook = createWorkBook(fieldNameArray, fieldValueArray, fieldDataList, dataDicList);
        workBook.write(os);
        os.close();
    }

    public SXSSFWorkbook createWorkBook(List<String> fieldNameArray, List<String> fieldValueArray,
                                        List<Object> fieldDataList, Map<String, Map<String, String>> dataDicMap)
            throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        int SPLIT_COUNT = SysBaseDefine.MAX_EXPORT_EXCEL_NUMBER;
        SXSSFWorkbook workBook = new SXSSFWorkbook();
        DataFormat dataFormat = workBook.createDataFormat();
        int rows = fieldDataList.size();
        int sheetNum = 0;

        // 获取分sheet数
        if (rows % SPLIT_COUNT == 0) {
            sheetNum = rows / SPLIT_COUNT;
        } else {
            sheetNum = rows / SPLIT_COUNT + 1;
        }

        // 创建表格头
        for (int i = 1; i <= sheetNum; i++) {
            SXSSFSheet sheet = workBook.createSheet("Page" + i);
            SXSSFRow titleRow = sheet.createRow(0);

            for (int j = 0; j < fieldNameArray.size(); j++) {
                /**
                 * 创建单元格
                 */
                SXSSFCell cell = titleRow.createCell(j);
                Object name = fieldNameArray.get(j);
                if (name != null) {
                    cell.setCellValue((String) name);
                } else {
                    cell.setCellValue("-");
                }
            }

            // 创建表格数据
            for (int k = 0; k < (rows < SPLIT_COUNT ? rows : SPLIT_COUNT); k++) {
                //创建行
                SXSSFRow dataRow = sheet.createRow(k + 1);
                // 获取map
                Object dataMap = fieldDataList.get((i - 1) * SPLIT_COUNT + k);
                for (int f = 0; f < fieldValueArray.size(); f++) {
                    String key = fieldValueArray.get(f);
                    Object objValue = "";
                    //如果数据集为MAP
                    if (dataMap instanceof Map) {
                        Map data = (Map) dataMap;
                        if (data.containsKey(key)) {
                            objValue = data.get(key);
                        }
                    } else {//如果数据集为对象
                        if (AmsBeanUtils.isContainField(dataMap.getClass(), key)) {
                            objValue = PropertyUtils.getNestedProperty(dataMap, key);
                        }
                    }
                    SXSSFCell cell = dataRow.createCell(f);
                    if (objValue instanceof BigDecimal) {
                        formatNumeric(workBook, dataFormat, cell);
                        cell.setCellValue(((BigDecimal) objValue).doubleValue());
                    } else if (objValue instanceof Double) {
                        formatNumeric(workBook, dataFormat, cell);
                        cell.setCellValue((Double) objValue);
                    } else {
                        String value = ConvertUtils.convert(objValue);
                        if (dataDicMap.containsKey(key)) {
                            if (null != dataDicMap.get(key)) {
                                value = dataDicMap.get(key).get(value);
                            }
                        }
                        cell.setCellValue(StringUtils.isEmpty(value) ? "" : value);
                    }
                }
            }
        }
        return workBook;
    }

    /**
     * 格式化数字
     */
    private void formatNumeric(SXSSFWorkbook workBook, DataFormat dataFormat, Cell cell) {
        CellStyle cellStyle = workBook.createCellStyle();
        cellStyle.setDataFormat(dataFormat.getFormat("#,##0.00"));
        cell.setCellStyle(cellStyle);
    }

}
